import { Injectable } from '@nestjs/common';
import { Request } from 'express';

@Injectable()
export class IpService {
  /**
   * 创建带超时的fetch请求
   * @param url 请求URL
   * @param timeout 超时时间（毫秒）
   * @param options fetch选项
   * @returns Promise<Response>
   */
  private async fetchWithTimeout(
    url: string,
    timeout: number = 3000,
    options: RequestInit = {}
  ): Promise<Response> {
    const controller = new AbortController();
    const timeoutId = setTimeout(() => controller.abort(), timeout);

    try {
      const response = await fetch(url, {
        ...options,
        signal: controller.signal,
      });
      clearTimeout(timeoutId);
      return response;
    } catch (error) {
      clearTimeout(timeoutId);
      if (error.name === 'AbortError') {
        throw new Error(`请求超时（${timeout}ms）`);
      }
      throw error;
    }
  }

  /**
   * 获取客户端真实IP地址
   * @param req Express请求对象
   * @returns 客户端IP地址
   */
  getClientIp(req: Request): string {
    let clientIp = '';

    // 1. 从X-Forwarded-For头部获取（代理/负载均衡）
    const forwardedFor = req.headers['x-forwarded-for'];
    if (forwardedFor) {
      clientIp = Array.isArray(forwardedFor)
        ? forwardedFor[0]
        : forwardedFor.toString().split(',')[0].trim();
    }

    // 2. 从X-Real-IP头部获取（Nginx代理）
    if (!clientIp) {
      const realIp = req.headers['x-real-ip'];
      if (realIp) {
        clientIp = Array.isArray(realIp) ? realIp[0] : realIp.toString();
      }
    }

    // 3. 从连接对象获取
    if (!clientIp && req.socket) {
      clientIp = req.socket.remoteAddress || '';

      // 处理IPv6格式
      if (clientIp.startsWith('::ffff:')) {
        clientIp = clientIp.substring(7);
      }
    }

    return clientIp || '0.0.0.0';
  }

  /**
   * 获取公网IP地址
   * @returns Promise<string> 公网IP地址
   */
  async getPublicIp(): Promise<string> {
    // 使用更稳定的IP查询服务（针对国内网络环境优化）
    const services = [
      // 第一批：稳定可靠的JSON服务
      'https://api64.ipify.org?format=json',
      'https://ipinfo.io/json',
      'https://api.ipapi.is',
      'https://ip-api.io/json',
      'https://api.ipify.org?format=json',

      // 第二批：纯文本服务（作为回退）
      'https://icanhazip.com',
      'https://ident.me',
      'https://checkip.amazonaws.com',
      'https://myexternalip.com/raw',
      'https://ifconfig.me',

      // 第三批：国外服务（网络好时可访问）
      'https://httpbin.org/ip',
      'https://api.ip.sb/ip',
      'https://api.myip.lol',
      'https://ip.useragentinfo.com/json',

      // 第四批：其他备用服务
      'https://ipv4.icanhazip.com',
      'https://ipv4.ident.me',
      'https://api.ipify.org',
    ];

    for (const service of services) {
      try {
        // 区分JSON和纯文本服务
        let response;
        const isJsonService =
          service.includes('json') ||
          service.includes('ipify.org?format=json') ||
          service.includes('ipinfo.io') ||
          service.includes('ipapi.is') ||
          service.includes('ip-api.io') ||
          service.includes('useragentinfo.com');

        if (isJsonService) {
          response = await this.fetchWithTimeout(service, 3000, {
            headers: {
              'User-Agent':
                'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
              Accept: 'application/json',
            },
          });
        } else {
          // 纯文本服务
          response = await this.fetchWithTimeout(service, 3000, {
            headers: {
              'User-Agent':
                'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
            },
          });
        }

        if (!response.ok) {
          throw new Error(`HTTP ${response.status}`);
        }

        let publicIp = '';

        if (isJsonService) {
          // JSON服务响应处理
          const data = await response.json();

          if (service.includes('ipify.org')) {
            publicIp = data.ip;
          } else if (service.includes('ipinfo.io')) {
            publicIp = data.ip;
          } else if (service.includes('useragentinfo.com')) {
            publicIp = data.ip || data.ip_address;
          } else if (service.includes('ipapi.is')) {
            publicIp = data.ip || data.ip_address;
          } else if (service.includes('ip-api.io')) {
            publicIp = data.ip || data.ip_string;
          } else if (service.includes('httpbin.org')) {
            publicIp = data.origin?.split(',')[0];
          } else if (service.includes('api.ip.sb')) {
            publicIp = data.ip || data.origin;
          } else if (service.includes('api.myip.lol')) {
            publicIp = data.ip || data.origin;
          }
        } else {
          // 纯文本服务响应处理
          const textIp = await response.text();
          publicIp = textIp.trim();
        }

        // 验证是否为有效的IPv4
        if (publicIp && this.isValidIpv4(publicIp)) {
          console.log(`✅ Success: ${service} -> ${publicIp}`);
          return publicIp;
        }
      } catch (error) {
        console.warn(`❌ Failed: ${service} -`, error.message);
        continue;
      }
    }

    // 如果所有服务都失败，返回一个友好的错误信息
    throw new Error('所有IP查询服务都不可用，请检查网络连接或稍后重试。');
  }

  /**
   * 验证IPv4地址格式
   * @param ip IP地址字符串
   * @returns 是否为有效IPv4
   */
  private isValidIpv4(ip: string): boolean {
    if (!ip || typeof ip !== 'string') return false;

    // IPv4格式验证
    const ipv4Regex = /^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/;
    const match = ip.match(ipv4Regex);

    if (match) {
      // 验证每个八位组是否在0-255范围内
      const octets = match.slice(1).map(Number);
      return octets.every(octet => octet >= 0 && octet <= 255);
    }

    return false;
  }
}
